import { _decorator, Component, Node, Vec3, CCFloat, CCBoolean, EventTouch, input, Input, Vec2 } from 'cc';
import { OrbitingBall } from './OrbitingBall';
const { ccclass, property } = _decorator;

// 攻击状态枚举
enum AttackState {
    IDLE,       // 空闲状态
    PREPARING,  // 准备攻击
    ATTACKING,  // 攻击中
    RETURNING   // 返回中
}

@ccclass('EllipseOrbitController')
export class EllipseOrbitController extends Component {
    @property(CCFloat)
    ellipseWidth: number = 400; // 椭圆宽度（长轴）

    @property(CCFloat)
    ellipseHeight: number = 200; // 椭圆高度（短轴）

    @property(CCFloat)
    orbitSpeed: number = 1.0; // 基准球轨道运动速度

    @property(CCFloat)
    rearrangeSpeed: number = 3.0; // 重新排列时的加速速度

    @property(CCBoolean)
    clockwise: boolean = true; // 是否顺时针旋转

    @property(CCFloat)
    rearrangeDuration: number = 0.5; // 重新排列的持续时间（秒）

    @property(CCFloat)
    attackPointAngle: number = 0; // 攻击点角度（弧度）

    @property(CCFloat)
    attackSpeed: number = 5.0; // 攻击速度

    @property(CCFloat)
    returnSpeed: number = 2.0; // 返回速度

    @property(Node)
    enemyContainer: Node = null!; // 敌人容器节点

    @property(CCFloat)
    attackDelay: number = 0.2; // 球体攻击延迟（秒）

    private orbitingBalls: Node[] = []; // 所有轨道上的球体节点
    private _angle: number = 0; // 当前角度
    private _isRearranging: boolean = false; // 是否正在重新排列
    private _rearrangeProgress: number = 0; // 重新排列进度
    private _previousAngles: Map<Node, number> = new Map(); // 重新排列前的角度
    private _attackState: AttackState = AttackState.IDLE; // 当前攻击状态
    private _attackProgress: number = 0; // 攻击进度
    private _returnProgress: number = 0; // 返回进度
    private _attackingBalls: Node[] = []; // 正在攻击的球体
    private _attackStartPositions: Map<Node, Vec3> = new Map(); // 攻击起始位置
    private _currentAttackIndex: number = 0; // 当前攻击的球体索引
    private _attackDelayTimer: number = 0; // 攻击延迟计时器
    private _enemyPositions: Vec3[] = []; // 敌人位置数组
    private _attackPath: Vec3[] = []; // 攻击路径点数组

    onLoad() {
        // 注册触摸事件
        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
    }

    onDestroy() {
        // 取消触摸事件
        input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
    }

    // 触摸开始事件
    onTouchStart(event: EventTouch) {
        if (this._attackState === AttackState.IDLE && this.orbitingBalls.length > 0) {
            this.startAttack();
        }
    }

    update(deltaTime: number) {
        // 根据当前状态执行不同的更新逻辑
        switch (this._attackState) {
            case AttackState.IDLE:
                this.updateIdleState(deltaTime);
                break;
            case AttackState.PREPARING:
                this.updatePreparingState(deltaTime);
                break;
            case AttackState.ATTACKING:
                this.updateAttackingState(deltaTime);
                break;
            case AttackState.RETURNING:
                this.updateReturningState(deltaTime);
                break;
        }
    }

    // 空闲状态更新
    updateIdleState(deltaTime: number) {
        // 根据旋转方向更新基准球角度
        const direction = this.clockwise ? -1 : 1;
        this._angle += direction * this.orbitSpeed * deltaTime;

        // 保持角度在 0-2π 范围内
        if (this._angle > Math.PI * 2) {
            this._angle -= Math.PI * 2;
        } else if (this._angle < 0) {
            this._angle += Math.PI * 2;
        }

        // 更新重新排列进度
        if (this._isRearranging) {
            this.updateRearrangeProgress(deltaTime);
        }

        // 更新所有球体位置
        this.updateAllBallPositions();
    }

    // 准备攻击状态更新
    updatePreparingState(deltaTime: number) {
        // 所有球体加速移动到攻击点
        this._attackProgress += this.attackSpeed * deltaTime;
        this._attackProgress = Math.min(this._attackProgress, 1);

        for (let i = 0; i < this.orbitingBalls.length; i++) {
            const ball = this.orbitingBalls[i];
            if (!ball || !ball.isValid) continue;

            const ballScript = ball.getComponent(OrbitingBall);
            if (!ballScript) continue;

            // 计算目标角度（攻击点角度）
            const targetAngle = this.attackPointAngle;

            // 计算当前角度
            const currentAngle = ballScript.getCurrentAngle();
            const angleDiff = this.calculateShortestAngleDifference(currentAngle, targetAngle);

            // 应用加速效果
            const acceleratedAngle = currentAngle + angleDiff * this._attackProgress;

            // 计算椭圆上的位置
            const x = this.ellipseWidth * Math.cos(acceleratedAngle);
            const y = this.ellipseHeight * Math.sin(acceleratedAngle);

            // 设置球体位置
            ball.setPosition(new Vec3(x, y, 0));
            ballScript.setCurrentAngle(acceleratedAngle);
        }

        // 检查是否到达攻击点
        if (this._attackProgress >= 1) {
            this.startAttacking();
        }
    }

    // 攻击状态更新
    updateAttackingState(deltaTime: number) {
        // 更新攻击延迟计时器
        this._attackDelayTimer += deltaTime;

        // 检查是否可以发射下一个球体
        if (this._attackDelayTimer >= this.attackDelay && this._currentAttackIndex < this.orbitingBalls.length) {
            this._attackDelayTimer = 0;
            this.launchNextBall();
        }

        // 更新攻击中的球体
        for (let i = this._attackingBalls.length - 1; i >= 0; i--) {
            const ball = this._attackingBalls[i];
            if (!ball || !ball.isValid) {
                this._attackingBalls.splice(i, 1);
                continue;
            }

            const ballScript = ball.getComponent(OrbitingBall);
            if (!ballScript) {
                this._attackingBalls.splice(i, 1);
                continue;
            }

            // 获取攻击起始位置
            const attackStartPos = this._attackStartPositions.get(ball) || ball.position.clone();

            // 更新球体攻击状态
            if (ballScript.updateAttack(deltaTime, attackStartPos, this._attackPath)) {
                // 如果球体攻击完成，从攻击列表中移除
                this._attackingBalls.splice(i, 1);

                // 如果球体攻击次数用完，从轨道移除
                if (ballScript.getAttackCount() <= 0) {
                    this.removeBallFromOrbit(ball);
                }
            }
        }

        // 检查是否所有球体都完成攻击
        if (this._attackingBalls.length === 0 && this._currentAttackIndex >= this.orbitingBalls.length) {
            this.startReturning();
        }
    }

    // 发射下一个球体
    launchNextBall() {
        if (this._currentAttackIndex >= this.orbitingBalls.length) return;

        const ball = this.orbitingBalls[this._currentAttackIndex];
        if (!ball || !ball.isValid) {
            this._currentAttackIndex++;
            return;
        }

        const ballScript = ball.getComponent(OrbitingBall);
        if (!ballScript) {
            this._currentAttackIndex++;
            return;
        }

        // 记录攻击起始位置
        this._attackStartPositions.set(ball, ball.position.clone());

        // 添加到攻击列表
        this._attackingBalls.push(ball);

        // 通知球体开始攻击
        ballScript.onAttackStart(this._attackPath);

        // 更新当前攻击索引
        this._currentAttackIndex++;
    }

    // 返回状态更新
    updateReturningState(deltaTime: number) {
        this._returnProgress += this.returnSpeed * deltaTime;
        this._returnProgress = Math.min(this._returnProgress, 1);

        for (let i = 0; i < this.orbitingBalls.length; i++) {
            const ball = this.orbitingBalls[i];
            if (!ball || !ball.isValid) continue;

            const ballScript = ball.getComponent(OrbitingBall);
            if (!ballScript) continue;

            // 计算返回目标角度（攻击点的对面）
            const returnAngle = (this.attackPointAngle + Math.PI) % (Math.PI * 2);

            // 计算当前角度
            const currentAngle = ballScript.getCurrentAngle();
            const angleDiff = this.calculateShortestAngleDifference(currentAngle, returnAngle);

            // 应用减速效果
            const decelatedAngle = currentAngle + angleDiff * this._returnProgress;

            // 计算椭圆上的位置
            const x = this.ellipseWidth * Math.cos(decelatedAngle);
            const y = this.ellipseHeight * Math.sin(decelatedAngle);

            // 设置球体位置
            ball.setPosition(new Vec3(x, y, 0));
            ballScript.setCurrentAngle(decelatedAngle);
        }

        // 检查是否返回完成
        if (this._returnProgress >= 1) {
            this.finishReturning();
        }
    }

    // 开始攻击
    startAttack() {
        this._attackState = AttackState.PREPARING;
        this._attackProgress = 0;

        // 获取敌人位置并生成攻击路径
        this.generateAttackPath();

        // 通知所有球体开始准备攻击
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                ballScript.onAttackPrepare();
            }
        }
    }

    // 生成攻击路径
    generateAttackPath() {
        // 获取敌人位置
        this.updateEnemyPositions();

        // 计算攻击点位置
        const attackPointX = this.ellipseWidth * Math.cos(this.attackPointAngle);
        const attackPointY = this.ellipseHeight * Math.sin(this.attackPointAngle);
        const attackPoint = new Vec3(attackPointX, attackPointY, 0);

        // 计算返回点位置（攻击点的对面）
        const returnAngle = (this.attackPointAngle + Math.PI) % (Math.PI * 2);
        const returnPointX = this.ellipseWidth * Math.cos(returnAngle);
        const returnPointY = this.ellipseHeight * Math.sin(returnAngle);
        const returnPoint = new Vec3(returnPointX, returnPointY, 0);

        // 生成攻击路径
        this._attackPath = this.calculatePathThroughPoints(attackPoint, this._enemyPositions, returnPoint);
    }

    // 计算经过所有点的路径
    calculatePathThroughPoints(startPoint: Vec3, throughPoints: Vec3[], endPoint: Vec3): Vec3[] {
        const path: Vec3[] = [];

        // 添加起点
        path.push(startPoint.clone());

        // 添加所有经过点
        for (const point of throughPoints) {
            path.push(point.clone());
        }

        // 添加终点
        path.push(endPoint.clone());

        // 使用Catmull-Rom样条插值生成平滑路径
        return this.catmullRomInterpolation(path, 20); // 20个插值点
    }

    // Catmull-Rom样条插值
    catmullRomInterpolation(points: Vec3[], segmentsPerSection: number): Vec3[] {
        const interpolatedPoints: Vec3[] = [];

        if (points.length < 2) return points;

        // 添加第一个点
        interpolatedPoints.push(points[0].clone());

        // 对每对点进行插值
        for (let i = 0; i < points.length - 1; i++) {
            const p0 = i === 0 ? points[0] : points[i - 1];
            const p1 = points[i];
            const p2 = points[i + 1];
            const p3 = i === points.length - 2 ? points[i + 1] : points[i + 2];

            // 生成插值点
            for (let t = 0; t <= 1; t += 1 / segmentsPerSection) {
                const t2 = t * t;
                const t3 = t2 * t;

                // Catmull-Rom公式
                const x = 0.5 * ((2 * p1.x) + (-p0.x + p2.x) * t +
                    (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +
                    (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3);

                const y = 0.5 * ((2 * p1.y) + (-p0.y + p2.y) * t +
                    (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
                    (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);

                interpolatedPoints.push(new Vec3(x, y, 0));
            }
        }

        // 添加最后一个点
        interpolatedPoints.push(points[points.length - 1].clone());

        return interpolatedPoints;
    }

    // 更新敌人位置
    updateEnemyPositions() {
        this._enemyPositions = [];
        const enemies = this.getEnemies();

        for (const enemy of enemies) {
            if (enemy && enemy.isValid) {
                this._enemyPositions.push(enemy.position.clone());
            }
        }
        //根据x的位置进行排序，从右到左
        this._enemyPositions.sort((a, b) => b.x - a.x);
    }

    // 开始攻击敌人
    startAttacking() {
        this._attackState = AttackState.ATTACKING;
        this._attackingBalls = [];
        this._attackStartPositions.clear();
        this._currentAttackIndex = 0;
        this._attackDelayTimer = 0;

        // 更新敌人位置并重新生成攻击路径
        this.generateAttackPath();
    }

    // 开始返回
    startReturning() {
        this._attackState = AttackState.RETURNING;
        this._returnProgress = 0;

        // 通知所有球体开始返回
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                ballScript.onReturnStart();
            }
        }
    }

    // 完成返回
    finishReturning() {
        this._attackState = AttackState.IDLE;

        // 检查是否还有球体可以继续攻击
        let hasAttackCount = false;
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript && ballScript.getAttackCount() > 0) {
                hasAttackCount = true;
                break;
            }
        }

        // 如果还有球体可以攻击，且敌人还存在，继续准备攻击
        if (hasAttackCount && this.getEnemies().length > 0) {
            this.startAttack();
        }
    }

    // 获取所有敌人
    getEnemies(): Node[] {
        if (!this.enemyContainer) return [];
        return this.enemyContainer.children;
    }

    // 更新所有球体位置
    updateAllBallPositions() {
        const ballCount = this.orbitingBalls.length;
        if (ballCount === 0) return;

        // 计算每个球体的目标位置
        const angleOffset = (Math.PI * 2) / ballCount;

        for (let i = 0; i < ballCount; i++) {
            const ball = this.orbitingBalls[i];
            if (!ball || !ball.isValid) continue;

            // 获取球体脚本
            const ballScript = ball.getComponent(OrbitingBall);
            if (!ballScript) continue;

            // 计算目标角度
            let targetAngle = this._angle + (i * angleOffset);

            // 如果正在重新排列，并且不是基准球，应用加速效果
            if (this._isRearranging && i > 0) {
                const previousAngle = this._previousAngles.get(ball) || ballScript.getCurrentAngle();
                const angleDiff = this.calculateShortestAngleDifference(previousAngle, targetAngle);

                // 应用加速效果
                const acceleratedAngle = previousAngle + angleDiff * this._rearrangeProgress;
                targetAngle = acceleratedAngle;
            }

            // 计算椭圆上的位置
            const x = this.ellipseWidth * Math.cos(targetAngle);
            const y = this.ellipseHeight * Math.sin(targetAngle);

            // 设置球体位置
            ball.setPosition(new Vec3(x, y, 0));

            // 更新球体的当前角度
            ballScript.setCurrentAngle(targetAngle);
        }

        // 检查重新排列是否完成
        if (this._isRearranging && this._rearrangeProgress >= 1) {
            this.onRearrangeComplete();
        }
    }

    // 计算最短角度差
    calculateShortestAngleDifference(from: number, to: number): number {
        let difference = to - from;
        while (difference > Math.PI) difference -= 2 * Math.PI;
        while (difference < -Math.PI) difference += 2 * Math.PI;
        return difference;
    }

    // 更新重新排列进度
    updateRearrangeProgress(deltaTime: number) {
        // 使用加速速度计算进度
        this._rearrangeProgress += (this.rearrangeSpeed / this.rearrangeDuration) * deltaTime;
        this._rearrangeProgress = Math.min(this._rearrangeProgress, 1);
    }

    // 重新排列完成
    onRearrangeComplete() {
        this._isRearranging = false;
        this._rearrangeProgress = 0;
        this._previousAngles.clear();

        // 通知所有球体重新排列完成
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                ballScript.onRearrangeComplete();
            }
        }
    }

    // 添加球体到轨道
    addBallToOrbit(ball: Node) {
        if (this.orbitingBalls.includes(ball)) return;

        // 保存当前所有球体的角度
        this.saveCurrentAngles();

        this.orbitingBalls.push(ball);

        // 获取球体脚本
        const ballScript = ball.getComponent(OrbitingBall);
        if (ballScript) {
            const newIndex = this.orbitingBalls.indexOf(ball);
            ballScript.updateOrbitIndex(newIndex);

            // 设置新球体的初始角度为基准球的角度
            ballScript.setCurrentAngle(this._angle);
        }

        // 开始重新排列
        this.startRearranging();
    }

    // 保存当前所有球体的角度
    private saveCurrentAngles() {
        this._previousAngles.clear();
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                this._previousAngles.set(ball, ballScript.getCurrentAngle());
            }
        }
    }

    // 从轨道移除球体
    removeBallFromOrbit(ball: Node) {
        const index = this.orbitingBalls.indexOf(ball);
        if (index !== -1) {
            // 保存当前所有球体的角度
            this.saveCurrentAngles();

            this.orbitingBalls.splice(index, 1);

            // 更新剩余球体的索引
            this.updateAllBallIndices();

            // 开始重新排列
            this.startRearranging();
        }
    }

    // 更新所有球体的轨道索引
    private updateAllBallIndices() {
        for (let i = 0; i < this.orbitingBalls.length; i++) {
            const ball = this.orbitingBalls[i];
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                ballScript.updateOrbitIndex(i);
            }
        }
    }

    // 开始重新排列
    startRearranging() {
        if (this.orbitingBalls.length <= 1) return;

        this._isRearranging = true;
        this._rearrangeProgress = 0;
        // this._rearrangeStartTime = Date.now();

        // 通知所有球体开始重新排列
        for (const ball of this.orbitingBalls) {
            const ballScript = ball.getComponent(OrbitingBall);
            if (ballScript) {
                ballScript.onRearrangeStart();
            }
        }
    }

    // 获取基准球角度
    getBaseAngle(): number {
        return this._angle;
    }

    // 获取轨道上的所有球体
    getOrbitingBalls(): Node[] {
        return this.orbitingBalls;
    }

    // 获取球体数量
    getBallCount(): number {
        return this.orbitingBalls.length;
    }

    // 设置旋转方向
    setRotationDirection(clockwise: boolean) {
        this.clockwise = clockwise;
    }

    // 设置基准球速度
    setOrbitSpeed(speed: number) {
        this.orbitSpeed = speed;
    }

    // 设置重新排列速度
    setRearrangeSpeed(speed: number) {
        this.rearrangeSpeed = speed;
    }

    // 设置重新排列持续时间
    setRearrangeDuration(duration: number) {
        this.rearrangeDuration = duration;
    }

    // 设置攻击速度
    setAttackSpeed(speed: number) {
        this.attackSpeed = speed;
    }

    // 设置返回速度
    setReturnSpeed(speed: number) {
        this.returnSpeed = speed;
    }

    // 设置攻击延迟
    setAttackDelay(delay: number) {
        this.attackDelay = delay;
    }

    // 清空所有球体
    clearAllBalls() {
        this.orbitingBalls = [];
        this._angle = 0;
        this._isRearranging = false;
        this._rearrangeProgress = 0;
        this._previousAngles.clear();
        this._attackState = AttackState.IDLE;
        this._attackingBalls = [];
        this._attackStartPositions.clear();
        this._currentAttackIndex = 0;
        this._attackDelayTimer = 0;
        this._enemyPositions = [];
        this._attackPath = [];
    }

    // UI 按钮方法
    onSetClockwise() { this.setRotationDirection(true); }
    onSetCounterClockwise() { this.setRotationDirection(false); }

    // 攻击按钮
    onAttackButtonClick() {
        if (this._attackState === AttackState.IDLE && this.orbitingBalls.length > 0) {
            this.startAttack();
        }
    }
}